package com.wyedu.qqServer.service;

import com.wyedu.qqMessageTransfer.qqMessageTransfer;
import com.wyedu.qqOfflineMessage.MessageQueue;
import com.wyedu.qqcommon.Message;
import com.wyedu.qqcommon.MessageType;
import com.wyedu.qqcommon.User;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Scanner;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * 这里是服务器,在9999监听
 * 等待客户端的连接并保持通信
 */
public class QQServer {
    Object object = new Object();
    //创建一个指定端口号为9999的服务器
    private ServerSocket ss = null;
    private static ConcurrentHashMap<String,User> validUsers = new ConcurrentHashMap<>();
    static {
        validUsers.put("100",new User("100","123456"));
        validUsers.put("200",new User("200","123456"));
        validUsers.put("至尊宝",new User("至尊宝","123456"));
    }
    //获取所有创建好的用户的方法
    public static String getUserId(){
        Iterator<String> iterator = validUsers.keySet().iterator();
        StringBuffer sb = new StringBuffer();
        while (iterator.hasNext()){
            sb.append(iterator.next()).append(" ");
        }
        return sb.toString();
    }
    private boolean checkUser(String id,String passwd){
        //先判断数据库中是否有这个用户
        //如果没有就返回null
        if(validUsers.getOrDefault(id,null)!= null){
            //如果有这个用户就判断密码是否正确
            return validUsers.get(id).getPasswd().equals(passwd);
        }
        return false;
    }
    public QQServer() throws IOException {
        //端口可以写在配置文件
       try {
           System.out.println("服务器在9999端口号监听.....");
           ss = new ServerSocket(9999);
           Thread ServerMessage = new Thread(()->{
               try (Scanner scanner = new Scanner(System.in)){

                   while (true){
                       System.out.println("1.群消息推送     2.关闭服务器");
                       if(scanner.nextLine().equals("1")){
                       System.out.print("请输入要推送的消息->");
                        String message = scanner.nextLine();
                        //获取所有的用户id(在线)
                       String[] userid = ManageServerConnectClientThread.getOnLineUsers().split(" ");
                       //获取所有用户的连接(socket)
                       for (String id:userid) {
                           if(id.equals("")){
                               break;
                           }
                           Socket socket = ManageServerConnectClientThread.getServerConnectClientThread(id).getSocket();
                           Message message1 = new Message();
                           Date date = new Date();
                           SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
                           message1.setContent(message);
                           message1.setSender("服务器");
                           message1.setMesType(MessageType.MESSAGE_COMM_MES);
                           message1.setSendTime(dateFormat.format(date));
                           new ObjectOutputStream(socket.getOutputStream()).writeObject(message1);
                       }
                   }else {
                           System.out.println("正在关闭服务器....");
                           String[] userid = ManageServerConnectClientThread.getOnLineUsers().split(" ");
                           for (String id:userid) {
                               if(id.equals("")){
                                   break;
                               }
                               Socket socket = ManageServerConnectClientThread.getServerConnectClientThread(id).getSocket();
                               Message message1 = new Message();
                               message1.setMesType(MessageType.MESSAGE_CLIENT_EXIT);
                               new ObjectOutputStream(socket.getOutputStream()).writeObject(message1);
                               ManageServerConnectClientThread.dleServerConnectClientThread(id);

                           }

                          System.exit(0);
                       }
                   }
               }catch (Exception e){
                   e.printStackTrace();
               }
           });
           ServerMessage.start();
           Thread t1 = new Thread(()->{
           while (true){
               //这里可以采用wait,如果有新的连接建立那就唤醒这个
               synchronized (object){
                   try {
                       object.wait();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
               BlockingQueue<Message> bq = null;
                String[]array = ManageServerConnectClientThread.getOnLineUsers().split(" ");
               for (String id:array) {
                   if(id.equals(" ")){
                       break;
                   }
                   //获取所有在线用户
                   //如果有用户上线就判断是否有留言
                   if(ManageServerConnectClientThread.getServerConnectClientThread(id) != null){
                       //获取当前socket

                       //此时该对象上线
                       //此时进行接收离线的消息
                       if((bq = MessageQueue.getMessageQueue(id)) != null) {
                           //获取成功该队列就删除该队列在map中对应的值
                           assert bq.peek() != null;
                           String requestId = bq.peek().getSender();
                           //如果发送的用户离线,就不要发送
                            if(ManageServerConnectClientThread.getServerConnectClientThread(requestId) == null){
                                for (Message message:bq ) {
                                    try {
                                        MessageQueue.AddOfflineMessage(id,message);
                                    } catch (InterruptedException ex) {
                                        ex.printStackTrace();
                                    }
                                }
                            }else {

                                qqMessageTransfer qmt = new qqMessageTransfer(ManageServerConnectClientThread.getServerConnectClientThread(requestId).getSocket());
                                //不为空进入
                                for (Message message1 : bq) {

                                    switch (message1.getMesType()) {
                                        case MessageType.MESSAGE_COMM_MES:
                                            //用户进行私聊
                                            qmt.privateMessage(message1);
                                            break;
                                        case MessageType.MESSAGE_COMM_FILE:
                                            //用户发送文件
                                            qmt.sendFile(message1);
                                            break;

                                    }
                                }

                            }
                       }

                   }
               }
           }
           });
           t1.start();
           while (true){
               Socket socket = ss.accept();//一直读取客户端传来的连接
               System.out.println("获取客户端"+socket.getInetAddress().getHostAddress()+" "+socket.getPort()+"的连接");
               try {
                   ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                   ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                   //获取客户端传来的用户信息
                   User u = (User) ois.readObject();

                   Message message = new Message();
                   if(checkUser(u.getUserId(), u.getPasswd())){
                       //登录成功
                       System.out.println("用户"+u.getUserId()+"登陆成功");
                       message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);
                       //此时与客户端建立连接
                       //创建一个线程和客户端保持通信,该线程持有socket对象
                       ServerConnectClientThread scct = new ServerConnectClientThread(u.getUserId(), socket);

                       //启动该线程
                       scct.start();
                       //把该线程对象放入到一个集合中管理
                       ManageServerConnectClientThread.addServerConnectClientThread(u.getUserId(), scct);
                       //返回构建好的信息对象

                       oos.writeObject(message);
                       synchronized (object){
                           object.notify();
                       }
                   }else {
                       //登陆失败
                       System.out.println("用户"+u.getUserId()+"登陆失败");

                       message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
                       oos.writeObject(message);
                       socket.close();//登陆失败关闭socket
                       System.out.println("用户"+u.getUserId()+"断开连接");


                   }

               }catch (Exception e){
                   e.printStackTrace();
               }

           }
        }catch (Exception e){
           e.printStackTrace();
       }finally {
           ss.close();
       }
    }

     //需要判断是否连接成功
}
